package com.zmc.lostfound.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zmc.lostfound.common.exception.MyException;
import com.zmc.lostfound.common.utils.PageResult;
import com.zmc.lostfound.common.utils.Result;
import com.zmc.lostfound.system.dao.FeedbackDao;
import com.zmc.lostfound.system.entity.FeedbackEntity;
import com.zmc.lostfound.system.entity.FunctionEntity;
import com.zmc.lostfound.system.service.FeedbackService;
import com.zmc.lostfound.system.service.FunctionService;
import com.zmc.lostfound.system.vo.FeedbackInfoVO;
import com.zmc.lostfound.system.vo.FeedbackQueryVO;
import com.zmc.lostfound.system.vo.FeedbackSaveVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author ZMC
 * @description 反馈信息管理业务实现
 * @email 2869581855@qq.com
 */
@Service
public class FeedbackServiceImpl extends ServiceImpl<FeedbackDao, FeedbackEntity> implements FeedbackService {

    private final FunctionService functionService;

    private final ThreadPoolExecutor threadPoolExecutor;

    public FeedbackServiceImpl(FunctionService functionService, ThreadPoolExecutor threadPoolExecutor) {
        this.functionService = functionService;
        this.threadPoolExecutor = threadPoolExecutor;
    }

    /**
     * 多条件查询用户反馈信息
     *
     * @param feedbackQueryVO 用户反馈查询请求体
     * @return PageResult
     */
    @Override
    public PageResult queryPage(FeedbackQueryVO feedbackQueryVO) {
        Integer pageNo = feedbackQueryVO.getPageNo();
        Integer pageSize = feedbackQueryVO.getPageSize();
        PageResult pageResult = new PageResult(pageNo, pageSize);

        // 查询所有功能模块信息
        CompletableFuture<Map<Long, String>> functionFuture = CompletableFuture.supplyAsync(() -> {
            List<FunctionEntity> functionList = functionService.findAll();
            if (CollectionUtil.isEmpty(functionList)) {
                MyException.throwException("查询失败: 功能模块信息不存在");
            }
            return functionList.stream()
                    .collect(Collectors.toMap(FunctionEntity::getId, FunctionEntity::getFunctionName));
        }, threadPoolExecutor);

        // 多条件查询用户反馈信息
        CompletableFuture<Page<FeedbackEntity>> feedbackFuture = CompletableFuture.supplyAsync(() -> {
            QueryWrapper<FeedbackEntity> queryWrapper = new QueryWrapper<>();
            Long userId = feedbackQueryVO.getUserId();
            Long functionId = feedbackQueryVO.getFunctionId();
            Integer type = feedbackQueryVO.getType();
            queryWrapper.eq(userId != null, "user_id", userId)
                    .eq(functionId != null, "function_id", functionId)
                    .eq(type != null, "type", type)
                    .orderByDesc("id");
            return this.page(new Page<>(pageNo, pageSize), queryWrapper);
        }, threadPoolExecutor);

        // 等待上述两个异步任务都执行完，再封装到用户反馈响应体
        CompletableFuture<Void> future = functionFuture.thenAcceptBothAsync(feedbackFuture, (functionMap, feedbackPage) -> {
            long total = feedbackPage.getTotal();
            if (total <= 0) {
                pageResult.setDataList(null);
                pageResult.setTotalCount(0);
                pageResult.setTotalPage(0);
            } else {
                List<FeedbackInfoVO> feedbackInfoVOList = feedbackPage.getRecords().stream()
                        .map(feedbackEntity -> {
                            FeedbackInfoVO feedbackInfoVO = BeanUtil.copyProperties(feedbackEntity, FeedbackInfoVO.class);
                            feedbackInfoVO.setFunctionName(functionMap.get(feedbackEntity.getFunctionId()));
                            return feedbackInfoVO;
                        })
                        .collect(Collectors.toList());
                pageResult.setDataList(feedbackInfoVOList);
                pageResult.setTotalCount(Math.toIntExact(total));
                pageResult.calculateTotalPage();
            }
        }, threadPoolExecutor);
        future.join();
        return pageResult;
    }

    /**
     * 按id查询用户反馈信息
     *
     * @param id 反馈id
     * @return FeedbackEntity
     */
    @Override
    public FeedbackEntity queryInfoById(Long id) {
        if (id == null || id <= 0) {
            MyException.throwException("查询失败: 反馈id不能为null且必须大于0");
        }
        return this.getById(id);
    }

    /**
     * 新增用户反馈信息
     *
     * @param feedbackSaveVO 反馈信息新增/修改请求体
     * @return Result
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result insertFeedback(FeedbackSaveVO feedbackSaveVO) {
        FeedbackEntity feedbackEntity = BeanUtil.copyProperties(feedbackSaveVO, FeedbackEntity.class);
        if (!this.save(feedbackEntity)) {
            MyException.throwException("反馈提交失败");
        }
        return Result.ok("反馈提交成功，感谢您的反馈！");
    }

    /**
     * 修改用户反馈信息
     *
     * @param feedbackSaveVO 反馈信息新增/修改请求体
     * @return Result
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result updateFeedback(FeedbackSaveVO feedbackSaveVO) {
        FeedbackEntity feedbackEntity = BeanUtil.copyProperties(feedbackSaveVO, FeedbackEntity.class);
        if (!this.updateById(feedbackEntity)) {
            MyException.throwException("修改反馈信息失败");
        }
        return Result.ok("修改成功");
    }

    /**
     * 按反馈ids批量删除反馈信息
     *
     * @param feedbackIds 反馈ids
     * @return Result
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result deleteBatchByIds(List<Long> feedbackIds) {
        if (CollectionUtil.isEmpty(feedbackIds)) {
            MyException.throwException("删除失败: 主键ids为空");
        }
        this.removeByIds(feedbackIds);
        return Result.ok("删除成功");
    }

    /**
     * 按用户id和系统功能id删除用户反馈信息
     *
     * @param functionId 系统功能id
     * @param userId     反馈用户id
     * @return Result
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result deleteByUserIdAndFunctionId(Long userId, Long functionId) {
        if (userId == null && functionId == null) {
            MyException.throwException("用户id与响系统功能id不能同时为null");
        }
        this.remove(new QueryWrapper<FeedbackEntity>()
                .eq(userId != null, "user_id", userId)
                .eq(functionId != null, "function_id", functionId));
        return Result.ok("删除成功");
    }

}